﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Media;
using LumiSoft.Net.RTP;
using LumiSoft.Net.Media;
using LumiSoft.Net.Media.Codec;
using LumiSoft.Net.Media.Codec.Audio;
using TEL.WinMediaWPF.Audio.Wav;
using TEL.WinMediaWPF.DTMF;

namespace TEL.WinMediaWPF.Audio
{
    /// <summary>
    /// This class implements RTP audio player.
    /// </summary>
    public class RTP_AudioPlayer
    {
        private AudioOutDevice m_pOutputDevice = null;
        private RTP_Session m_pSession = null;
        private RTP_ReceiveStream m_pRtpStream = null;
        private AudioOut m_pPlayer = null;
    //    private WavePlayer m_pAudioPlayer = null;
        
        private WAVFile m_pWavFile = null;
       // private System.Media.SoundPlayer m_Medialayer = null;
        private object mLock = new object();

        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="device">Audio output device.</param>
        /// <param name="session">RTP session.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>device</b> or <b>session</b> is null reference.</exception>
        public RTP_AudioPlayer(AudioOutDevice device, RTP_Session session)
        {
            if (device == null)
            {
                throw new ArgumentNullException("device");
            }
            if (session == null)
            {
                throw new ArgumentNullException("session");
            }

            m_pOutputDevice = device;
            m_pSession = session;

            m_pSession.NewReceiveStream += new EventHandler<RTP_ReceiveStreamEventArgs>(m_pSession_NewReceiveStream);

            m_pPlayer = new AudioOut(device, 8000, 16, 1);
            //m_Medialayer = new SoundPlayer();
            //m_Medialayer.Stream = new MemoryStream();
        }

        public int Volume
        {
            get { return m_pPlayer == null ? 0 : m_pPlayer.Volume; }
            set { m_pPlayer.Volume = value; }
        }

        /// <summary>
        /// Начинаем запись в <b>WAV</b> фаил
        /// </summary>
        /// <param name="fileName">Имя нового фаила </param>
        public void StartSaving(string fileName)
        {
            if (File.Exists(fileName)) File.Delete(fileName);

            m_pWavFile = new WAVFile();
            m_pWavFile.Create(fileName, false, 8000, 16);
            
            // m_pWavFile.Create(fileName, false, 11025, 8);
        }

        /// <summary>
        /// Закрытия фаила
        /// </summary>
        public void StopSaving()
        {
            if (m_pWavFile != null)
            {
                m_pWavFile.Close();
                m_pWavFile = null;
            }
        }

        void ReseiverToWav(byte[] content)
        {
            if (m_pWavFile == null) return;
            MemoryStream stream = new MemoryStream(content);
            int bits = m_pWavFile.BitsPerSample / 8;
            int r = bits;
            byte[] bytes = new byte[bits];
            while (r > 0)
            {
                r = stream.Read(bytes, 0, bits);

                m_pWavFile.AddSample_ByteArray(bytes);
                
            }


        }


        void m_pSession_NewReceiveStream(object sender, RTP_ReceiveStreamEventArgs e)
        {
            if (m_pRtpStream != null)
            {
                m_pRtpStream.PacketReceived -= new EventHandler<RTP_PacketEventArgs>(m_pRtpStream_PacketReceived);
                m_pRtpStream.StrEvent -= new EventHandler<RTP_ReceiveStream.StrEventArgs>(m_pRtpStream_StrEvent);
                m_pRtpStream = null;
            }

            // Attach new audio stream.
            m_pRtpStream = e.Stream;
            m_pRtpStream.PacketReceived += new EventHandler<RTP_PacketEventArgs>(m_pRtpStream_PacketReceived);
            m_pRtpStream.StrEvent += new EventHandler<RTP_ReceiveStream.StrEventArgs>(m_pRtpStream_StrEvent);
            //if (ReceiverEvent != null)
            //    ReceiverEvent(this, new MediaLogEventArgs("NewReceiveStream", "Создан новый ресивер поток"));
        }

        void m_pRtpStream_StrEvent(object sender, RTP_ReceiveStream.StrEventArgs e)
        {
            //if (ReceiverEvent != null)
            //    ReceiverEvent(this, new MediaLogEventArgs("RtpStream_PacketReceived  тест индекс пакета", e.Message));
        }

        #region method Dispose

        /// <summary>
        /// Cleans up any resources being used.
        /// </summary>
        public void Dispose()
        {
            m_pRtpStream.PacketReceived -= new EventHandler<RTP_PacketEventArgs>(m_pRtpStream_PacketReceived);
            m_pRtpStream = null;
            if (m_pPlayer != null)
            {
                m_pPlayer.Dispose();
                m_pPlayer = null;
            }
            //if (m_Medialayer != null)
            //{
            //    m_Medialayer.Dispose();
            //    m_Medialayer = null;
            //}
        }

        #endregion

        public event EventHandler<AudioReceiverEventArgs> AudioReceiverEvent = null;
        public event EventHandler<ErrorEventArgs> AudioReceiverErrorEvent = null;
        public event EventHandler<MediaLogEventArgs> ReceiverEvent = null;


        #region Events handling
        Codec codec = null;
        #region method m_pRtpStream_PacketReceived

        /// <summary>
        /// This method is called when new RTP packet received.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event data.</param>
        private void m_pRtpStream_PacketReceived(object sender, RTP_PacketEventArgs e)
        {
            try
            {
                m_pSession.Payloads.TryGetValue(e.Packet.PayloadType, out codec);
                if (codec == null)
                {
                    throw new ArgumentNullException("codec");
                }

                byte[] decodedData = codec.Decode(e.Packet.Data, 0, e.Packet.Data.Length);
                if (AudioReceiverEvent != null)
                    AudioReceiverEvent(this, new AudioReceiverEventArgs(codec.Name, e.Packet.Data.Length,
                                                                              decodedData.Length, m_pOutputDevice.Name,
                                                                              e.Packet.SeqNo));
              
                m_pPlayer.Write(decodedData, 0, decodedData.Length);
             
                //MemoryStream stream = new MemoryStream(decodedData);
                //WAVFileMemory m_pWavFile = new WAVFileMemory();
                //m_pWavFile.Create("", false, 8000, 16);
                //m_pWavFile.AddSample_ByteArray(decodedData);
                //m_pWavFile.Close();
                //m_pWavFile.mStream.Position = 0;
                //m_Medialayer.Stream = m_pWavFile.mStream;
                //lock (mLock)
                //{
                    
                //    m_Medialayer.Play();
                //}

                //m_pWavFile.Close(null);

                if (m_pWavFile != null) ReseiverToWav(decodedData);
            }
            catch (Exception error)
            {
                if (AudioReceiverErrorEvent != null)
                    AudioReceiverErrorEvent(this, new ErrorEventArgs(error));
            }
        }

        #endregion

        #endregion


        #region Tone

        public void TonePlay(Stream stream)
        {
            stream.Position = 0;
            int i = 1;
           byte[] buffer = new byte[320];
            while (i>0)
            {
               i=  stream.Read(buffer, 0, buffer.Length);
            m_pPlayer.Write(buffer, 0, buffer.Length);
            }
            
        }

        #endregion
    }
}